/**
 * 
 */
package com.jeesuite.bestpl.task;

import java.io.Serializable;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import com.jeesuite.bestpl.dao.entity.PostEntity;
import com.jeesuite.bestpl.dao.mapper.PostEntityMapper;
import com.jeesuite.cache.command.RedisHashMap;
import com.jeesuite.common2.lock.DistributeLockTemplate;
import com.jeesuite.common2.lock.LockCaller;
import com.jeesuite.common2.lock.redis.RedisDistributeLock;
import com.jeesuite.scheduler.AbstractJob;
import com.jeesuite.scheduler.JobContext;

/**
 * 帖子统计入库定时任务
 * @description <br>
 * @author <a href="mailto:vakinge@gmail.com">vakin</a>
 * @date 2017年11月29日
 */
public class PostStatStoreageTask extends AbstractJob{

	private static final String POST_STAT_KEY = "post_stat";

	private @Autowired PostEntityMapper postmapper;
	
	@Override
	public void doJob(JobContext context) throws Exception {
		
		Map<String, PostStat> datas = null;
		RedisHashMap redisHash = new RedisHashMap(POST_STAT_KEY);
		// 读取的时候使用分布式锁
		RedisDistributeLock lock = new RedisDistributeLock(POST_STAT_KEY);
		lock.lock();
		try {
			datas = redisHash.getAll();
			redisHash.remove();
		} finally {
			lock.unlock();
		}
		
		if(datas == null || datas.isEmpty())return;
		
		for (PostStat postStat : datas.values()) {
			PostEntity postEntity = postmapper.selectByPrimaryKey(postStat.getPostId());
			postEntity.setCommentCount(postEntity.getCommentCount() + postStat.getCommentCount());
			postEntity.setViewCount(postEntity.getViewCount() + postStat.getViewCount());
			
			postmapper.updateByPrimaryKeySelective(postEntity);
		}
		
	}

	@Override
	public boolean parallelEnabled() {
		return false;
	}
	
	/**
	 * 
	 * @param postId
	 * @param type 1:浏览数，2：评论数
	 */
	public static void addStatData(final int postId,final int type){
		String key = String.valueOf(postId);
		RedisHashMap redisHash = new RedisHashMap(POST_STAT_KEY);
		//使用分布式锁，这个是分布式一个简单的模板方法
		DistributeLockTemplate.execute(POST_STAT_KEY, new LockCaller<PostStat>() {

			@Override
			public PostStat onHolder() {
				PostStat stat = redisHash.getOne(key);
				if(stat == null)stat = new PostStat(postId);
				stat.add(type);
				redisHash.set(key, stat);
				return null;
			}

			@Override
			public PostStat onWait() {
				//
				try {Thread.sleep(1000);} catch (Exception e) {}
				//
				addStatData(postId, type);
				return null;
			}
		});
	}

	public static class PostStat implements Serializable{
		private static final long serialVersionUID = 1L;
		private int postId;
		private int commentCount;
		private int viewCount;
		
		public PostStat() {}
		
		public PostStat(int postId) {
			this.postId = postId;
		}
		public int getPostId() {
			return postId;
		}
		public void setPostId(int postId) {
			this.postId = postId;
		}
		public int getCommentCount() {
			return commentCount;
		}
		public void setCommentCount(int commentCount) {
			this.commentCount = commentCount;
		}
		public int getViewCount() {
			return viewCount;
		}
		public void setViewCount(int viewCount) {
			this.viewCount = viewCount;
		}
		
		public void add(int type){
			if(type == 1){
				viewCount++;
			}else{
				commentCount++;
			}
		}
	}
}
